<?php

declare(strict_types=1);

namespace Plugin\NEK\CodeGenerator\Command\Creater;

use App\Exception\BusinessException;
use Hyperf\Command\Annotation\Command;
use Hyperf\DbConnection\Db;
use Hyperf\Support\Filesystem\Filesystem;
use Mine\AppStore\Command\AbstractCommand;
use Mine\Helper\Str;
use Plugin\NEK\CodeGenerator\Model\SettingGenerateTables;
use Plugin\NEK\CodeGenerator\Service\SettingGenerateTablesService;
use Symfony\Component\Console\Input\InputOption;

#[Command()]
class FillPlugin extends AbstractCommand
{
    public function __construct(
        protected readonly Filesystem $filesystem,
        protected readonly SettingGenerateTablesService $settingGenerateTablesService,
        protected readonly SettingGenerateTables $settingGenerateTables,
        ?string $name = null,
    ) {
        parent::__construct($name);
    }

    protected const COMMAND_NAME = 'fill';

    protected string $description = 'fill plugin';
    public function __invoke(): int
    {
        $tablePath = $this->input->getOption('path');
        $namespace = $this->input->getOption('namespace');
        $package = $this->input->getOption('package');
        $tables = $this->getTableName($tablePath . '/Migrations');
        $this->settingGenerateTablesService->loadTable(['names' => $tables]);
        $updateData = [
            'package_name' => $package,
            'namespace' => $namespace,
            'generate_menus' => ['save', 'update', 'delete'],
            'generate_type' => 2,
            'columns' => []
        ];
        $updateIDs = $this->settingGenerateTables
            ::whereIn('table_name', array_column($tables, 'name'))
            ->pluck('id')
            ->toArray();
        foreach ($updateIDs as $id) {
            $updateData['id'] = $id;
            $this->settingGenerateTablesService->updateTableAndColumns($updateData);
        }
        $this->settingGenerateTablesService->generate($updateIDs, false);
        $this->createMenuSeeder($package, $tablePath);
        $this->changeUninstall($tablePath, $package);
        return AbstractCommand::SUCCESS;
    }

    private function getTableName($path): array
    {
        if ($this->filesystem->isDirectory($path)) {
            $files = $this->filesystem->files($path);
            return array_map(function ($file) {
                $parts = explode('_', $file->getFilenameWithoutExtension());
                $tableName = $parts[5];
                for ($i = 6; $i < count($parts) - 1; $i++) {
                    $tableName .= '_' . $parts[$i];
                }
                $comment = Db::select(
                    "SELECT TABLE_COMMENT 
                    FROM INFORMATION_SCHEMA.TABLES 
                    WHERE TABLE_SCHEMA = ? AND TABLE_NAME = ?",
                    [env('DB_DATABASE'), $tableName]
                )[0]->TABLE_COMMENT ?? 'no comment';
                return [
                    'name' => $tableName,
                    'comment' => $comment
                ];
            }, $files);
        }
        $this->output->error(\sprintf('migrations directory is accepted', $path));
        throw new BusinessException();
    }

    protected function configure(): void
    {
        $this
            ->addOption('path', null, InputOption::VALUE_REQUIRED, 'Plugin Path')
            ->addOption('namespace', null, InputOption::VALUE_REQUIRED, 'namespace')
            ->addOption('package', null, InputOption::VALUE_REQUIRED, 'package name');
    }

    private function createMenuSeeder($package, $path)
    {
        $fileName = 'Init' . str_replace('/', '', $package) . 'Menu';
        $path = $path . '/Seeders/';
        if (!file_exists($path)) {
            mkdir($path, 0755, true);
        }
        $moduleString = '';
        $tables = $this->settingGenerateTables::where('package_name', str_replace('/', '\\', $package))->get()->toArray();
        foreach ($tables as $table) {
            $moduleString .= $this->buildStub('Module', [
                'MENU_TITLE' => $table['table_comment'],
                'NAME' => strtolower($package) . ':' . Str::camel($table['table_name']),
                'I18N' => strtolower($package) . '.menu.' . Str::camel($table['table_name']),
                'PATH' => $package . '/' . Str::studly($table['table_name']),
                'COMPONET' => $package . '/views/' . Str::camel($table['table_name']) . '/index',
            ]);
        }
        $content = $this->buildStub('Menu', [
            'CLASS_NAME' => $fileName,
            'MODULE' => $moduleString,
            'PACKAGE_NAME' => Str::studly(str_replace('/', '', $package)),
            'TITLE' => $package,
            'PATH' => $package,
        ]);
        file_put_contents($path . $fileName . '.php', $content);
        $this->output->success(\sprintf('%s Created Successfully', $fileName));
    }

    public function getStubDirectory(): string
    {
        return realpath(__DIR__) . '/stubs';
    }

    public function buildStub(string $stub, array $replace): string
    {
        $stubPath = $this->getStubDirectory() . '/' . $stub . '.stub';
        if (! file_exists($stubPath)) {
            throw new \RuntimeException(\sprintf('File %s does not exist', $stubPath));
        }
        $stubBody = file_get_contents($stubPath);
        foreach ($replace as $key => $value) {
            $stubBody = str_replace('%' . $key . '%', $value, $stubBody);
        }
        return $stubBody;
    }

    public function changeUninstall($path, $package)
    { 
        $filePath = $path . '/../src/UninstallScript.php';
        $content = file_get_contents($filePath);
        $name = str_replace('/', '', $package);
        $content = str_replace("deleteMenus('')", "deleteMenus('{$name}Route')", $content);
        file_put_contents($filePath, $content);
    }
}
